﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Net.NetworkInformation;
using System.Configuration;
using System.Threading;
using Microsoft.Synchronization.Data;
using System.Data.Linq;

using TIMETABLEASY.TokenAuthentification;

namespace TIMETABLEASY
{
    /// <summary>
    /// Logique d'interaction pour Window2.xaml
    /// </summary>
    public partial class Window2 : Window
    {
        //Local_db db;

        dbDataContext db_remote;
        Local_db db_local;

        SingletonTokenUser token = SingletonTokenUser.GetInstance();

        public string database_mode;
        public string ip_address;
        public string connection_mode;

        public Window2()
        {

            #region Initialization

            InitializeComponent();
            
            
            //On récupère l'adresse ip enregistrée dans la config
            ip_address = getIpAddress();

            //On teste si la connexion internet fonctionne et si la bdd est opérationnelle
            if (testInternetConnection())
            {

                try
                {
                    if (sync_database())
                    {
                        connection_status_label.Content = "Connected to remote database";
                    }

                }
                catch (Exception)
                {
                    MessageBox.Show("Impossible to synchronize the local and the remote database");
                    connection_status_label.Content = "Connected to remote database - Sync failed";
                }
                finally
                {
                    token.Database_mode = "online";
                    db_remote = new dbDataContext();
                    connection_mode = "online";
                }

            }

            else
            {

                System.Windows.Forms.DialogResult dlgResult = System.Windows.Forms.MessageBox.Show("WARNING : The software doesn't find any Internet Connection.\n\nDo you want to use the Offline Mode ?\nYou won't be able to modify any datas on the software.", "Database Configuration", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
                
                if (dlgResult == System.Windows.Forms.DialogResult.Yes)
                {
                    connection_status_label.Content = "Connected to local database - read only";
                    token.Database_mode = "offline";
                    connection_mode = "offline";

                    
                    db_local = new Local_db("Data Source=|DataDirectory|\\local_db.sdf;Max Database Size=2047");
                    

                }

                else
                {
                    connection_status_label.Content = "No Connection";
                    token.Database_mode = "offline";
                    connection_mode = "offline";
                }

            }

            #endregion

        }

        #region fonctions connection

        public bool signinConnection()
        {

            token.Is_perso_selected = true;

            if (home_name_textbox.Text != "" && home_password_textbox.Password != "")
            {

                String login_connection = home_name_textbox.Text;
                String password_connection = home_password_textbox.Password;


                foreach (administrators s in (from e in db_remote.administrators where (e.login.Equals(login_connection)) where (e.password.Equals(password_connection)) select e))
                {

                    token.User_level = SingletonTokenUser.Admin;
                    token.User_id = s.id;
                    token.User_login = s.login;
                    token.User_fistname = s.firstname;
                    token.User_surname = s.surname;
                    token.Is_perso_selected = true;
                    token.Notepad_enabled = (int)s.notepad_enabled;
                    token.Notepad_text = s.notepad_text;

                    Window1 fenetre1 = new Window1();


                    fenetre1.Show();

                    this.Close();
                    return true;
                }

                foreach (students s in (from e in db_remote.students where (e.login.Equals(login_connection)) where (e.password.Equals(password_connection)) select e))
                {
                    token.User_level = SingletonTokenUser.Student;
                    token.User_id = s.id;
                    token.User_login = s.login;
                    token.User_fistname = s.firstname;
                    token.User_surname = s.surname;
                    token.Notepad_enabled = (int)s.notepad_enabled;
                    token.Notepad_text = s.notepad_text;

                    token.User_campus = s.campus;

                    token.User_classe = s.classe;

                    token.TypeOfView = "Class";

                    classes css = (from i in db_remote.classes
                                 where i.name == s.classe
                                 select i).FirstOrDefault();

                    token.ValueOfView = css.id;
                    token.Is_perso_selected = true;

                    Window1 fenetre1 = new Window1();
                    
     
                    fenetre1.Show();

                    this.Close();

                    return true;
                }

                foreach (managers s in (from e in db_remote.managers where (e.login.Equals(login_connection)) where (e.password.Equals(password_connection)) select e))
                {
                    
                    token.User_level = SingletonTokenUser.Manager;
                    token.User_id = s.id;
                    token.User_login = s.login;
                    token.User_fistname = s.firstname;
                    token.User_surname = s.surname;
                    token.Notepad_enabled = (int)s.notepad_enabled;
                    token.Notepad_text = s.notepad_text;

                    token.User_campus = s.campus;

                    token.Is_perso_selected = true;

                    Window1 fenetre1 = new Window1();
                    fenetre1.Show();


                    this.Close();
                    return true;

                }

                foreach (teacher s in (from e in db_remote.teacher where (e.login.Equals(login_connection)) where (e.password.Equals(password_connection)) select e))
                {
                    token.User_level = SingletonTokenUser.Teacher;
                    token.User_id = s.id;
                    token.User_login = s.login;
                    token.User_fistname = s.firstname;
                    token.User_surname = s.surname;
                    token.Notepad_enabled = (int)s.notepad_enabled;
                    token.Notepad_text = s.notepad_text;

                    token.User_campus = s.campus;

                    token.User_classe = s.classe;

                    token.User_cursus = s.cursus;
                    token.User_is_student = (int) s.isStudent;
                    token.Is_perso_selected = true;

                    Window1 fenetre1 = new Window1();

                    

                    fenetre1.Show();

                    this.Close();
                    return true;

                }
                return false;

            }

            else
            {
                MessageBox.Show("Please enter a login or password.");
                return true;
            }


        }


        public bool signinConnection_offline()
        {

            token.Is_perso_selected = true;

            if (home_name_textbox.Text != "" && home_password_textbox.Password != "")
            {

                String login_connection = home_name_textbox.Text;
                String password_connection = home_password_textbox.Password;


                foreach (Administrators s in (from e in db_local.Administrators where (e.Login.Equals(login_connection)) where (e.Password.Equals(password_connection)) select e))
                {

                    token.User_level = SingletonTokenUser.Admin;
                    token.User_id = s.Id;
                    token.User_login = s.Login;
                    token.User_fistname = s.Firstname;
                    token.User_surname = s.Surname;
                    token.Is_perso_selected = true;
                    token.Notepad_enabled = (int)s.Notepad_enabled;
                    token.Notepad_text = s.Notepad_text;

                    Window1 fenetre1 = new Window1();


                    fenetre1.Show();

                    this.Close();
                    return true;
                }

                foreach (Students s in (from e in db_local.Students where (e.Login.Equals(login_connection)) where (e.Password.Equals(password_connection)) select e))
                {
                    token.User_level = SingletonTokenUser.Student;
                    token.User_id = s.Id;
                    token.User_login = s.Login;
                    token.User_fistname = s.Firstname;
                    token.User_surname = s.Surname;
                    token.Notepad_enabled = (int)s.Notepad_enabled;
                    token.Notepad_text = s.Notepad_text;

                    token.User_campus = s.Campus;

                    token.User_classe = s.Classe;

                    token.TypeOfView = "Class";

                    Classes css = (from i in db_local.Classes
                                   where i.Name == s.Classe
                                   select i).FirstOrDefault();

                    token.ValueOfView = css.Id;
                    token.Is_perso_selected = true;

                    Window1 fenetre1 = new Window1();


                    fenetre1.Show();

                    this.Close();

                    return true;
                }

                foreach (Managers s in (from e in db_local.Managers where (e.Login.Equals(login_connection)) where (e.Password.Equals(password_connection)) select e))
                {

                    token.User_level = SingletonTokenUser.Manager;
                    token.User_id = s.Id;
                    token.User_login = s.Login;
                    token.User_fistname = s.Firstname;
                    token.User_surname = s.Surname;
                    token.Notepad_enabled = (int)s.Notepad_enabled;
                    token.Notepad_text = s.Notepad_text;

                    token.User_campus = s.Campus;

                    token.Is_perso_selected = true;

                    Window1 fenetre1 = new Window1();
                    fenetre1.Show();


                    this.Close();
                    return true;

                }

                foreach (Teacher s in (from e in db_local.Teacher where (e.Login.Equals(login_connection)) where (e.Password.Equals(password_connection)) select e))
                {
                    token.User_level = SingletonTokenUser.Teacher;
                    token.User_id = s.Id;
                    token.User_login = s.Login;
                    token.User_fistname = s.Firstname;
                    token.User_surname = s.Surname;
                    token.Notepad_enabled = (int)s.Notepad_enabled;
                    token.Notepad_text = s.Notepad_text;

                    token.User_campus = s.Campus;

                    token.User_classe = s.Classe;

                    token.User_cursus = s.Cursus;
                    token.User_is_student = (int)s.IsStudent;
                    token.Is_perso_selected = true;

                    Window1 fenetre1 = new Window1();



                    fenetre1.Show();

                    this.Close();
                    return true;

                }
                return false;

            }

            else
            {
                MessageBox.Show("Please enter a login or password.");
                return true;
            }


        }

        private bool testInternetConnection()
        {
            Ping pingSender = new Ping();
            PingOptions options = new PingOptions();

            //Fragmentation du ping
            options.DontFragment = true;

            // Création d'un buffer 32 bits pour transmettre les données
            string ip = ip_address;
            string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
            byte[] buffer = Encoding.ASCII.GetBytes(data);
            int timeout = 128;

            //Réponse du ping
            try
            {
                PingReply reply = pingSender.Send(ip, timeout, buffer, options);

                if (reply.Status == IPStatus.Success)
                {
                    return true;
                }

                else
                {
                    return false;
                }
            }
            catch (Exception)
            {

                return false;
            }

        }

        private string getIpAddress()
        {
            //On récupère la chaine
            ConnectionStringSettingsCollection connectionStrings = ConfigurationManager.ConnectionStrings;

            //On la stocke dans un énumérateur (cas de plusieurs chaines)
            IEnumerator connectionStringsEnum = connectionStrings.GetEnumerator();

            //On fait les opérations sur la bonne chaine
            int i = 0;

            while (connectionStringsEnum.MoveNext())
            {
                string name = connectionStrings[i].Name;

                if (name == "TIMETABLEASY.Properties.Settings.dbConnectionString")
                {
                    string connectionsettings_temp = connectionStrings[name].ToString();
                    string[] connectionsettings = connectionsettings_temp.Split(';');

                    //On découpe la chaine pour récupérer l'adresse IP
                    string connectionlocation_temp = connectionsettings[0];
                    string[] connectionlocation = connectionlocation_temp.Split('=');
                    string address_ip = connectionlocation[1];

                    return address_ip;

                    ///////////////////////////////////////
                    //Structure de la chaine : Data Source=0.0.0.0;Initial Catalog=timetableasy;Persist Security Info=True;User ID=timetableasy;Password=password
                    //////////////////////////////////////
                }

                i++;
            }

            return "";
        }


        private bool sync_database()
        {
            Sync sync_loading = new Sync();
            this.Hide();
            sync_loading.Show();

            database_syncSyncAgent syncAgent = new database_syncSyncAgent();
            syncAgent.administrators.SyncDirection = Microsoft.Synchronization.Data.SyncDirection.Bidirectional;
            Microsoft.Synchronization.Data.SyncStatistics syncStats = syncAgent.Synchronize();

            if (syncStats.DownloadChangesApplied == 0 && syncStats.DownloadChangesFailed > 0)
            {
                MessageBox.Show("Warning : No data synchronized. Please contact your administrator");
            }

            else if (syncStats.DownloadChangesApplied > 0 && syncStats.DownloadChangesFailed > 0)
            {
                MessageBox.Show("Warning : some datas are not synchronized. The software may not work as expected");
            }

            sync_loading.Close();
            this.Show();
            
            return true;
        }

        #endregion

        #region controles connection

        private void home_signinButton_Click(object sender, RoutedEventArgs e)
        {
            if (connection_mode == "online")
            {
                try
                {
                    bool connection_ok = signinConnection();

                    if (!connection_ok)
                    {
                        MessageBox.Show("Your credentials don't exist. Please contact your administrator");

                    }
                }

                catch (Exception error)
                {
                    MessageBox.Show("An error occurs during connection. Please contact your administrator : " + error.ToString());
                }
            }

            else if (connection_mode == "offline")
            {
                try
                {
                    bool connection_ok = signinConnection_offline();

                    if (!connection_ok)
                    {
                        MessageBox.Show("Your credentials don't exist. Please contact your administrator");

                    }
                }

                catch (Exception error)
                {
                    MessageBox.Show("An error occurs during connection. Please contact your administrator : " + error.ToString());
                }
            }
        }

        #endregion

    }
}
